#include "ringbuf.h"

/* 单生产者/单消费者（ISR + 主循环）安全。
   约定：使用 N-1 容量法，满/空判定简单无歧义。 */

static inline size_t _next(size_t cur, size_t size) {
    ++cur;
    if (cur >= size) cur = 0;
    return cur;
}

void RingBuf_construct(RingBuf_Handle o, unsigned char *bufPtr, size_t bufSize)
{
    o->buf  = bufPtr;
    o->size = bufSize;
    o->head = 0;
    o->tail = 0;
    o->max  = 0;
}

bool RingBuf_isFull(RingBuf_Handle o)
{
    return _next(o->head, o->size) == o->tail;
}

int RingBuf_getCount(RingBuf_Handle o)
{
    size_t h = o->head;
    size_t t = o->tail;
    size_t cnt = (h >= t) ? (h - t) : (o->size - (t - h));
    return (int)cnt;
}

int RingBuf_getMaxCount(RingBuf_Handle o)
{
    return (int)o->max;
}

int RingBuf_put(RingBuf_Handle o, unsigned char data)
{
    size_t n = _next(o->head, o->size);
    if (n == o->tail) {
        return -1;
    }
    o->buf[o->head] = data;
    o->head = n;

    size_t cnt = (o->head >= o->tail) ? (o->head - o->tail)
                                      : (o->size - (o->tail - o->head));
    if (cnt > o->max) o->max = cnt;
    return (int)cnt;
}

int RingBuf_get(RingBuf_Handle o, unsigned char *data)
{
    if (o->head == o->tail) {
        return -1;
    }
    *data = o->buf[o->tail];
    o->tail = _next(o->tail, o->size);
    return RingBuf_getCount(o);
}

int RingBuf_peek(RingBuf_Handle o, unsigned char *data)
{
    if (o->head == o->tail) {
        return 0;
    }
    *data = o->buf[o->tail];
    return RingBuf_getCount(o);
}
